Skip to content

Conversation

gabrielmfern
Copy link
Member

@gabrielmfern gabrielmfern commented Aug 25, 2025

This pull request makes use of the new tailwindcss@4 API, and a new CSS parser called css-tree. It makes the code much simpler (since Tailwind now exposes a function to generate styles), much smaller (since we only need to bundle css-tree for a distribution issue csstree/csstree#352) and it gets slightly faster than the previous version.

The pull request also introduces a few changes to the changes we made for email compatibility to work well with the new CSS features used in tailwindcss@4.

Currently available on npm through @react-email/[email protected]

Compatibility

tailwindcss@4 introduces the use of some new CSS features in certain ways that email clients don't support, here's a list of them and the respective way of how we change the genreate CSS to have better email client support.

  • Uses oklch as the default color function, which is almost not supported at all: we convert it, and most other colors to rgb(red,green,blue,alpha) syntax
  • Uses calc expressions extensively (e.g. m-* utiltiies): we evaluate simple calc expressions which should be enough for the vast majority of the utilites that have
  • Uses border-radius:calc(Infinity*1px) instead of 9999px for rounded-full: Convert to using 9999px instead directly

There might still be some other compatibility issues that we can't see, and some ones that I suspect might not be supported so we still need to test it on Litmus before releasing a stable version.

Performance

After the initial changes to actually get tests working, I noticed performance issues, where just email rendering would get into a few a seconds for not such a complicated email template. One of the reasons was code introduced in this pull request to deal with compatibility issues, but it was mainly because of repeated parse calls to css-tree. I knew this was the case after profiling with Node.js's profiling and the flamegraphs in https://discoveryjs.github.io/cpupro.

Before tailwindcss@4, we were using using postcss which was the same CSS parser that was used for tailwindcss@3 so it made integration much simpler. Now, with tailwindcss@4 they're using their own seemingly proprietary minimal CSS parser that is not exposed, meaning we need to pick one ourselves. With that new parser, we end up also repeatedly parsing the CSS coming from tailwind instead of reusing what already has parsed under the hood.

To actually get reasonable performance running with tailwindcss@v4, by avoiding repeatedly parsing the CSS returned from the build function coming from tailwindcss, this pull request also introduces a new way of inlining styles for components.

Before this pull request, we would always inline styles for components and elements alike. But, for components we did not strip away the original classes that were associated with the inlined styles. Now, we only inline styles for elements, and not for any component, unless the component has a tailwindTreatAsElement = true property to it, which we do for some components now (e.g., Button).

This is actually a much more intuitive user experience than what we had before since it brings it closer to what users would already be used to when using tailwindcss.

@gabrielmfern gabrielmfern self-assigned this Aug 25, 2025
Copy link

changeset-bot bot commented Aug 25, 2025

⚠️ No Changeset found

Latest commit: 438d703

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

vercel bot commented Aug 25, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
react-email Ready Ready Preview Comment Oct 3, 2025 7:56pm
react-email-demo Ready Ready Preview Comment Oct 3, 2025 7:56pm

Copy link

pkg-pr-new bot commented Aug 25, 2025

Open in StackBlitz

@react-email/body

npm i https://pkg.pr.new/resend/react-email/@react-email/body@2425

@react-email/button

npm i https://pkg.pr.new/resend/react-email/@react-email/button@2425

@react-email/code-block

npm i https://pkg.pr.new/resend/react-email/@react-email/code-block@2425

@react-email/code-inline

npm i https://pkg.pr.new/resend/react-email/@react-email/code-inline@2425

@react-email/components

npm i https://pkg.pr.new/resend/react-email/@react-email/components@2425

@react-email/container

npm i https://pkg.pr.new/resend/react-email/@react-email/container@2425

@react-email/heading

npm i https://pkg.pr.new/resend/react-email/@react-email/heading@2425

@react-email/hr

npm i https://pkg.pr.new/resend/react-email/@react-email/hr@2425

@react-email/img

npm i https://pkg.pr.new/resend/react-email/@react-email/img@2425

@react-email/link

npm i https://pkg.pr.new/resend/react-email/@react-email/link@2425

@react-email/preview

npm i https://pkg.pr.new/resend/react-email/@react-email/preview@2425

@react-email/preview-server

npm i https://pkg.pr.new/resend/react-email/@react-email/preview-server@2425

react-email

npm i https://pkg.pr.new/resend/react-email@2425

@react-email/tailwind

npm i https://pkg.pr.new/resend/react-email/@react-email/tailwind@2425

@react-email/text

npm i https://pkg.pr.new/resend/react-email/@react-email/text@2425

commit: 438d703

Copy link

socket-security bot commented Oct 3, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​types/​css-tree@​2.3.101001007579100
Addedcss-tree@​3.1.010010010081100

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants